#ifndef SERVER_H_
#define SERVER_H_

#include "serverCache.h"
#include <iostream>
#include "commonConfig.h"
#include "serverSocket.h"
#include "serverModeloRespuesta.h"
#include "commonModeloProtocolo.h"
#include "serverHilo.h"
#include <list>

typedef std::pair <std::string, std::string> tDato;

class ClientHandler;

class Server: public Hilo {
private:
	Cache* cache;
	std::list <ClientHandler*> *conexiones;
	ServerSocket socket;

public:
	explicit Server(unsigned int puerto);

	/* Implementa la función virtual procedente de la clase Hilo*/
	virtual void ejecutar();

	virtual ~Server();

	Cache* getCache() const;

	/* Envía datos a través del socket.*/
	int escribir(ClientHandler *cliente, void *buf, size_t tamanio);

	/* Recibe datos a través del socket. */
	int leer(ClientHandler *cliente, void *buf, size_t tamanio);

    void setCache(Cache *cache);

    /* Dada una variable que modele al protocolo, separa del argumento
     * la clave y el valor y devuelve un par con los string correspondientes.*/
    tDato* obtenerClaveValor(const ModeloProtocolo& modelo);

    /* Dada una variable que modele al protocolo procesa la operacion
     *  pedida por el cliente y devuelve un string con el resultado del pedido*/
    std::string procesarOperacion(const ModeloProtocolo& modelo);


    /* Dado el fileDescriptor del cliente atendido, recibe el pedido realizado por el mismo
     * leyendo los datos enviados por el cliente. Devuelve una variable que
     * modela a la respuesta con los resultados del pedido.*/
    ModeloRespuesta* obtenerPedido(ClientHandler *cliente);


    /* Dado el ClientHandler del cliente atendido y una variable que modele la
     * respuesta del servidor, responde al pedido realizado por el cliente
     * enviando los datos al mismo. */
    void responderPedido(ClientHandler* cliente,
    					 ModeloRespuesta respuestaPedido);

    std::list<ClientHandler*>* getConexiones() const;

    /* Recibe un etero que representa un file descriptor. Revisa la lista de
     * conexiones en busqueda de clientes inactivos. En caso de que haya alguno,
     * reemplaza el fileDescriptor del inactivo (primera ocurrencia)
     * por el del nuevo y devuelve un true. Si no hay ningun cliente inactivo devuelve
     * false. */
     bool reemplazarClienteInactivo(int fdClienteNuevo);

     void cerrar();

     ServerSocket getSocket() const;
};

#endif /* SERVER_H_ */
